﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DSVISUAL.LocalDNS
{
    public class ListViewItemData
    {
        public ListViewItemData(ListViewItem ui, INotifyPropertyChanged data, EntityState state)
        {
            if (ui.ListView == null)
                throw new Exception("the ListViewItem should add to ListView first.");
            //set properties
            this.UIElement = ui;
            this.Data = data;
            this.DataState = state;
            this.Trackable = new Trackable(data, state);
            ui.Tag = this;

            //bind inner event
            data.PropertyChanged += Data_PropertyChanged;


            //notify changed to bind data at first time.
            this.NotifyDataChanged();
        }

        private void Data_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var dataType = Data.GetType();
            var columns = UIElement.ListView.Columns;
            var subItems = UIElement.SubItems;
            foreach (ColumnHeader item in columns)
            {
                var key = string.IsNullOrEmpty(item.Name) ? item.Text : item.Name;
                if (e.PropertyName.Equals(key, StringComparison.OrdinalIgnoreCase))
                {
                    var value = dataType.GetProperty(key).GetValue(Data);
                    if (subItems.Count - 1 < item.Index)
                    {
                        subItems.Add(value?.ToString());
                    }
                    else
                    {
                        subItems[item.Index].Text = value?.ToString();
                    }
                }
            }
            if (this.Trackable.State == EntityState.Unchanged)
            {
                this.Trackable.State = EntityState.Modified;
            }
        }

        public void NotifyDataChanged()
        {
            var properties = Data.GetType().GetProperties();
            foreach (var item in properties)
            {
                Data_PropertyChanged(this, new PropertyChangedEventArgs(item.Name));
            }
        }

        public INotifyPropertyChanged Data { get; set; }
        public EntityState DataState { get; private set; }
        public Trackable Trackable { get; }
        public ListViewItem UIElement { get; set; }
    }

    public static class ListViewItemExtension
    {
        public static Trackable AddItem(this ListView listView, INotifyPropertyChanged item, EntityState state)
        {
            var listViewItem = new ListViewItem();
            listView.Items.Add(listViewItem);
            if (listViewItem.ListView == null)
            {

            }
            return new ListViewItemData(listViewItem, item, state).Trackable;
        }
    }
}
